package src.javaStudy.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @program: AlgorithmTest
 * @description: 反射例子
 *
 * 其中forName方法是Class类的一个static成员方法，记住所有的Class对象都源于这个Class类，
 * 因此Class类中定义的方法将适应所有Class对象。这里通过forName方法，我们可以获取到Gum类
 * 对应的Class对象引用。从打印结果来看，调用forName方法将会导致Gum类被加载 (前提是Gum类从
 * 来没有被加载过)。
 *
 * @author: powerWriter
 * @create: 2019-06-20 22:22
 **/

class Candy extends Father{
    public String CandyName;
    public String name;
    private String guo;
    protected int count;

    @Override
    void DoSomething(){
        System.out.println("i am Candy!!!");
    }

    public int CountSum(int sum){
        return sum;
    }

    public String CountSum(String s){
        return "";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    static {   System.out.println("Loading Candy"); }
}

class Gum extends Father{
    static {   System.out.println("Loading Gum"); }

    @Override
    void DoSomething(){
        System.out.println("i am Gum!!!");
    }
}

class Cookie extends Father{

    @Override
    void DoSomething(){
        System.out.println("i am Cookie!!!");
    }

    static {   System.out.println("Loading Cookie"); }
}

class Father{
    public String name;
    public String phoneNum;
    private int age;
    protected String sex;

    void DoSomething(){
        System.out.println("i am Father!!!");
    }

    void Getname(String name){
        System.out.println(this.name = name);
    };
}

public class SweetShop {
    public static void print(Object obj) {
        System.out.println(obj);
    }
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //Duotai();
        //Reflec();
        ReflectionTime();
    }

    //反射获取类的属性
    static void Reflec(){
        Class clazz = null;
        try {
            clazz = Class.forName("src.javaStudy.reflection.Candy");
            Field[] f = clazz.getFields();          //只获取public的属性
            Field[] fs = clazz.getDeclaredFields(); //只获取子类的全部属性，不包括父类

            for (Field field : fs) {
                System.out.println("fs获取子类的全部属性："+field.getName());
            }
            for (Field field : f) {
                System.out.println("f获取子类和父类的public属性："+field.getName());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //对比反射/直接获取 耗时操作
    static void ReflectionTime() throws
            ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException
    {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            Candy stu = new Candy();
            stu.setName("幼儿园我最皮！");
            System.out.println(stu.getName());
        }
        long end = System.currentTimeMillis();

        long start1 = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            Class<?> clz = Class.forName("src.javaStudy.reflection.Candy");
            Candy stu = (Candy) clz.newInstance();
            Method method = clz.getMethod("setName", String.class);
            method.invoke(stu, "幼儿园我最皮！");
            System.out.println(stu.getName());
        }
        long end1 = System.currentTimeMillis();
        System.out.println("直接获取对象处理耗时："+(end - start));
        System.out.println("反射获取对象处理耗时："+(end1 - start1));
    }

    //多台的例子
    static void Duotai()
    {
        //向上转型了，子类的属性方法就用不了了，此时以子类重写的方法为准
        Father candy = new Candy();
        Father gum = new Gum();
        Father cookie = new Cookie();

        candy.DoSomething();
        gum.DoSomething();
        cookie.DoSomething();
    }

}
